#include "ProcessTable.h"
#include "system.h"

ProcessTable::ProcessTable()
{
	processes = new Table(MAX_PROCESS);
	tableLock = new Lock("table lock");
	processCounter=0;
}

int Process::addThread(Thread* t)
{
	threadCounter++;
	executingThreads++;
	*(t->threadId) = threads->Put((void*)t);
	return *(t->threadId);
}

Process::Process(AddrSpace *s)
{
	threadCounter=0;
	executingThreads=0;
	space =s;
	processLock = new Lock("Process Lock");
	threads = new Table(MAX_THREADS);
}

int Process::remove(int i)
{
	if(threads->Get(i)!=0)
	{
		threads->Remove(i);
		threadCounter--;
		executingThreads--;
		return 1;
	}
	else
	{
		DEBUG('a',"No Process at i");
		return 0;
	}
}

int ProcessTable::addProcess(AddrSpace* space,Thread *t)
{
	Process *p = new Process(space);

#ifdef NETWORK
	//give the process its mailbox number and increment the mailbox number counter for the next process
	mailboxNumCounterLock->Acquire();
	p->mailboxNum = mailboxNumCounter;
	mailboxNumCounter++;
	mailboxNumCounterLock->Release();
#endif

	*(t->threadId) = p->addThread(t);
	*(t->processId) = processes->Put((void*)p);
	printf("Making process %i\n",*(t->processId));
	processCounter++;
	return 1;
}


int ProcessTable::sleepThread()
{
	if(((Process*)processes->Get(*(currentThread->processId)))->threads->Get(*(currentThread->threadId))!=0)
	{
		((Process*)processes->Get(*(currentThread->processId)))->executingThreads--;
		return 1;
	}
	else
	{
		ASSERT(FALSE);
		return 1;
	}
}

int ProcessTable::wakeThread()
{
	if(((Process*)processes->Get(*(currentThread->processId)))->threads->Get(*(currentThread->threadId))!=0)
	{
		((Process*)processes->Get(*(currentThread->processId)))->executingThreads++;
		return 1;
	}
	else
	{
		ASSERT(FALSE);
		return 1;
	}
}

int ProcessTable::addThread(Thread* t)
{
	printf("Adding thread to process %i\n",*(currentThread->processId));
	Process* p = ((Process*)processes->Get(*(currentThread->processId)));
	if(p!=0)
	{
		*(t->processId)=*(currentThread->processId);
		p->addThread(t);
		return 1;
	}
	else
	{
		DEBUG('a',"No Process Table Entry for this process\n");
		return 0;
	}
}

int ProcessTable::getRemainingThreads()
{
	Process* p = ((Process*)processes->Get(*(currentThread->processId)));
	if(p!=0)
	{
		return p->threadCounter;
	}
	else
	{
		ASSERT(FALSE);
		return 0;
	}
}

int ProcessTable::getExecutingThreads()
{
	Process* p = ((Process*)processes->Get(*(currentThread->processId)));
	if(p!=0)
	{
		return p->executingThreads;
	}
	else
	{
		printf("Process %i doesn't exist in process table\n",*(currentThread->processId));
		return 1;
	}
}

int ProcessTable::removeProcess()
{
	int p = ((int)processes->Get(*(currentThread->processId)));
	if(p!=0)
	{
		processes->Remove(p);
		processCounter--;
		return 1;
	}
	else
	{
		return 0;
	}
}

int ProcessTable::removeThread(int threadId)
{
	Process* p = ((Process*)processes->Get(*(currentThread->processId)));
	if(p!=0)
	{
		if(p->remove(threadId)!=0)
			return 1;
		else
		{
			return 0;
		}
	}
	else
	{
		ASSERT(FALSE);
		return 0;
	}
}

int ProcessTable::lockProcess()
{

	Process* p = ((Process*)processes->Get(*(currentThread->processId)));
	if(p!=0)
	{
		p->processLock->Acquire();
			return 1;
	}
	else
	{
		return 0;
	}
}

int ProcessTable::releaseProcess()
{
		
	Process* p = ((Process*)processes->Get(*(currentThread->processId)));
	if(p!=0)
	{
		p->processLock->Release();
	
			return 1;
	}
	else
	{
		
		return 0;
	}
}

void ProcessTable::lockTable()
{
	tableLock->Acquire();
}

void ProcessTable::releaseTable()
{
	tableLock->Release();
}
